library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_unsigned.all;
use ieee.numeric_std.all;

entity CompAD9826control is
port (  
      GReset       : IN  STD_LOGIC; 
      SYSCLK:         in STD_LOGIC;
		ClkADCprog   : IN STD_LOGIC;
		SyncInput : IN STD_LOGIC;
      SW:             in STD_LOGIC_VECTOR(7 downto 0);
      ADC_Dres     : OUT STD_LOGIC_VECTOR(15 downto 0);
      XFER1_N:            inout STD_LOGIC;
      OUFLOW1:        inout STD_LOGIC;
  --      OUTEN_N:        out STD_LOGIC;
      DataIn:         IN STD_LOGIC_VECTOR(7 downto 0);
      ADCCLK:         out STD_LOGIC;
      CDSCLK1:        out STD_LOGIC;
      CDSCLK2:        out STD_LOGIC;
      SCLK:           inout STD_LOGIC;
      SLOAD_N:            inout STD_LOGIC;
      SDATA:          inout STD_LOGIC;
      JP5IN:              inout STD_LOGIC_VECTOR(5 downto 1); -- note not on old board
      DEBUG1:         inout STD_LOGIC;--
      Dl:             out std_logic_vector(18 downto 0);--(18 downto 0);
      D_latch:        out std_logic_vector(18 downto 0);
  --      sample_weight:  out std_logic_vector(2 downto 0);
      ped_done:       out std_logic;
      cds_done:       out std_logic;
      accumulator:    out std_logic_vector(18 downto 0);
      addsub_out:     in std_logic_vector(18 downto 0);
      add_sub:        out STD_LOGIC;
      valid:          out std_logic;
      cin:            out std_logic--;
  --      mult_out:       in std_logic_vector(18 downto 0)
     );
end CompAD9826control;

architecture ArchCompAD9826control of CompAD9826control is 
--  signal D_latch:         std_logic_vector(15 downto 0);
--  signal Dl:              std_logic_vector(17 downto 0);
signal sigDl:                std_logic_vector(18 downto 0);
---1    signal accumulator: std_logic_vector(18 downto 0);
--signal accumulator:   std_logic_vector(15 downto 0);
--signal valid: std_logic;
  signal sigCDSCLK2: std_logic;
  signal sigADCCLK: std_logic;
  signal xmt_word:        STD_LOGIC_VECTOR(15 downto 0);
  signal xmt_out:         STD_LOGIC;
  signal bit_count:       unsigned(4 downto 0);
  signal spin_count:      unsigned(5 downto 0);
  signal machine_state:   std_logic_vector(3 downto 0);
  type config_state_type is (redo,
                             idle1,
                             idle2,
                             config_reg,
                             mux_reg,
                             pga_reg_red,
                             pga_reg_grn,
                             pga_reg_blu,
                             offset_red_reg,
                             offset_grn_reg,
                             offset_blu_reg,
                             write_out, clock_out
                            );
  signal config_state:    config_state_type;
  type control_state_type is (idle, clamp, clamptosample,sample,
  sampletoadcclock, adcclock, latchhighdata,hightolow,latch_low,pedtosig,xfer);
  signal control_state:   control_state_type;
--  signal cds_done :           std_logic;
  signal sample_count:    unsigned(3 downto 0); 
  signal clock_count:     unsigned(8 downto 0);--unsigned(6 downto 0);
  type trig_state_type is (idle_trig, trig_out);
  signal trig_state:  trig_state_type;
  signal ltclock_count:       unsigned(8 downto 0);--unsigned(6 downto 0);
  type lttrig_state_type is (idle_lttrig, lttrig_out);
  signal lttrig_state:    lttrig_state_type;
  signal ppol_n, integ_n,jp5in1sync,jp5in2sync:   std_logic;
  signal trigger,trig_start,trig_s,ppolar_s_n,integ_s_n:          std_logic;
---------------------------------------------------------------------------------
  type sample_number_type is (grp1_s1,grp1_s2,grp1_s3,grp1_s4,grp2_s1,grp2_s2,
  grp2_s3,grp2_s4);
  signal sample_number: sample_number_type;

  constant weight1: std_logic_vector(2 downto 0):= "001";
  constant weight2: std_logic_vector(2 downto 0):= "010";
  constant weight4: std_logic_vector(2 downto 0):= "100";
--  signal mult_out:    std_logic_vector(18 downto 0);
--------------------------------------------------------------------
-- Configuration switch settings -- note switch ON=0
  alias config_enable:    std_logic is SW(0);--s1
  alias CCD:              std_logic is SW(1);--s2
  alias mux_3:            std_logic is SW(2);--s3
  alias sh_mode:          std_logic is SW(3);--s4
  alias internal_trig:    std_logic is SW(4);--s5
  alias sw_speed:         std_logic is SW(5);--s6

  alias reg_addr:     std_logic_vector is xmt_word(14 downto 12);
  alias word_space:   std_logic_vector is xmt_word(11 downto 9);
-- configuration constants
  constant space_pattern : std_logic_vector(2 downto 0) := "000";
  constant ir_mode1 : std_logic_vector(8 downto 0)  := "011001000"; 
-- rng=4V,Vref=int,3CH=off,SHA=on,clamp=4V,pwr=on,0,2bytes=on
  constant ir_mode3 : std_logic_vector(8 downto 0)  := "011101000"; 
-- rng=4V,Vref=int,3CH=on,SHA=on,clamp=4V,pwr=on,0,2bytes=on
  constant CCD_mode1 : std_logic_vector(8 downto 0) := "011000000"; ------------------"011011000";
-- rng=4V,Vref=int,3CH=off,CDS=on,clamp=4V,pwr=on,0,2bytes=on
  constant CCD_mode3 : std_logic_vector(8 downto 0) := "011111000"; 
-- rng=4V,Vref=int,3CH=on,CDS=on,clamp=4V,pwr=on,0,2bytes=on
  constant mux1_mode : std_logic_vector(8 downto 0) := "011000000";--"011000000"; 
-- RGB,red out only
  constant mux3_mode : std_logic_vector(8 downto 0) := "010000000";--"011110000"; 
-- RGB,red green blue out
  constant pga_mode : std_logic_vector(8 downto 0) := "000000000"; 
-- gain = 1
  constant pga_g2_25: std_logic_vector(8 downto 0) := "000101010"; 
-- gain = 2.25
  constant pga_g6: std_logic_vector(8 downto 0) := "000111111"; 
-- gain = 6
  constant offset_mode : std_logic_vector(8 downto 0) := "000000000"; 
-- offset = 0
--------------------------------------------------------------------
begin
 Config : process(ClkADCprog, GReset) 
 begin
  if (GReset = '1') then   
   xmt_word <= (others => '0');
   --xmt_out <= '0';
   SLOAD_N <= '1';
   SCLK <= '1';
   bit_count <= "10000";
   machine_state <= "0000";
   config_state <= redo;
  elsif (ClkADCprog'event and ClkADCprog = '1') then  
   case (config_state) is
    when redo =>
     SLOAD_N <= '1';
     SCLK <= '0';
     machine_state <= "0000";
     if (config_enable = '1') then --s1=off
      xmt_word(15) <= '0'; -- write
      config_state <= config_reg;
     else 
      config_state <= idle1;
     end if;
    when config_reg =>
     SLOAD_N <= '1';
     SCLK <= '0';
     machine_state <= "0001";
     bit_count <= "10000";
     reg_addr <= "000"; -- config reg addr
     word_space <= space_pattern;
     if (CCD = '1') then -- CCD CDS mode s2=off
      if (mux_3 = '0') then -- single channel s3=on
       xmt_word(8 downto 0) <= CCD_mode1(8 downto 0);
      else -- 3 channel
       xmt_word(8 downto 0) <= CCD_mode3(8 downto 0);
      end if;
     else -- IR SHA modes 2=on
      if (mux_3 = '0') then -- single channel s3=on
       xmt_word(8 downto 0) <= ir_mode1(8 downto 0);
      else -- 3 channel
       xmt_word(8 downto 0) <= ir_mode3(8 downto 0);
      end if;
     end if;
     config_state <= write_out;
    when write_out =>
     if (bit_count > 0) then 
      SLOAD_N <= '0';
      SCLK <= '0';
      xmt_out <= xmt_word(15);
      xmt_word <= xmt_word(14 downto 0) & '0';
      config_state <= clock_out;
     else
      SLOAD_N <= '1';
      SCLK <= '0';
      case machine_state is
       when "0001" =>
        config_state <= mux_reg;
       when "0010" =>
        config_state <= pga_reg_red;
       when "0011" =>
        config_state <= pga_reg_grn;
       when "0100" =>
        config_state <= pga_reg_blu;
       when "0101" =>
        config_state <= offset_red_reg;
       when "0110" =>
        config_state <= offset_grn_reg;
       -- when "0111" =>
       --  config_state <= offset_blu_reg;
       --  when "1000" =>
        config_state <= idle2;
       when others =>
        config_state <= idle2;
      end case;
     end if;
    when clock_out =>
     SLOAD_N <= '0';
     SCLK <= '1';
     bit_count <= bit_count - 1;
     config_state <= write_out;
    when mux_reg =>
     SLOAD_N <= '1';
     SCLK <= '1';
     machine_state <= "0010";
     bit_count <= "10000";
     reg_addr <= "001"; -- mux reg addr
     word_space <= space_pattern;
     if (mux_3 = '1') then --s3=off
      xmt_word(8 downto 0) <= mux3_mode(8 downto 0);
     else
      xmt_word(8 downto 0) <= mux1_mode(8 downto 0);
     end if;
     config_state <= write_out;
    when pga_reg_red => -- set to gain=1 for now
     SLOAD_N <= '1';
     SCLK <= '1';
     machine_state <= "0011";
     bit_count <= "10000";
     reg_addr <= "010"; -- red pga reg addr
     word_space <= space_pattern; 
     xmt_word(8 downto 0) <= pga_mode(8 downto 0);
     config_state <= write_out;
    when pga_reg_grn => -- set to gain=1 for now
     SLOAD_N <= '1';
     SCLK <= '1';
     machine_state <= "0100";
     bit_count <= "10000";
     reg_addr <= "011"; -- grn pga reg addr
     word_space <= space_pattern;
     xmt_word(8 downto 0) <= pga_mode(8 downto 0);
     --xmt_word(8 downto 0) <= pga_g2_25(8 downto 0);
     config_state <= write_out;
    when pga_reg_blu => -- set to gain=6 for now
     SLOAD_N <= '1';
     SCLK <= '1';
     machine_state <= "0101";
     bit_count <= "10000";
     reg_addr <= "100"; -- blu pga reg addr
     word_space <= space_pattern;
     xmt_word(8 downto 0) <= pga_mode(8 downto 0);
     --xmt_word(8 downto 0) <= pga_g6(8 downto 0);  -- g=X6
     config_state <= write_out;
    when offset_red_reg => -- set to zero for now
     SLOAD_N <= '1';
     SCLK <= '1';
     machine_state <= "0110";
     bit_count <= "10000";
     reg_addr <= "101"; -- red offset
     word_space <= space_pattern; 
     xmt_word(8 downto 0) <= offset_mode(8 downto 0);
     config_state <= write_out;
    when offset_grn_reg => -- set to zero for now
     SLOAD_N <= '1';
     SCLK <= '1';
     machine_state <= "0111";
     bit_count <= "10000";
     reg_addr <= "110"; -- grn offset
     word_space <= space_pattern; 
     xmt_word(8 downto 0) <= offset_mode(8 downto 0);
     config_state <= write_out;
     --  when offset_blu_reg => -- set to zero for now
        --      SLOAD_N <= '1';
        --      SCLK <= '1';
        --      machine_state <= "1000";
        --      bit_count <= "10000";
        --      reg_addr <= "111"; -- blu offset
        --      word_space <= space_pattern; 
        --      xmt_word(8 downto 0) <= offset_mode(8 downto 0);
        --      config_state <= write_out;
     when idle1 =>
         SLOAD_N <= '1';
         SCLK <= '1';
         config_state <= idle1;
     when idle2 =>
         SLOAD_N <= '1';
         SCLK <= '0';
         config_state <= idle1;
     when others =>
         config_state <= idle1;
     end case;
  end if;
end process;

Control : process(SYSCLK, GReset, trig_start, CCD,sh_mode, mux_3 ) -- one channel mode only
begin
 if (GReset = '1') then
  --                  OUTEN_N <= '0';
  --                 OUFLOW1 <= '0';
  --                  D_latch <=(others => '0');
  accumulator <= (others => '0');
  --                  ped_done <= '0';
  --                  cds_done <= '0';
  --                  add_sub <= '1';
  sigDl <= (others => '0');
  CDSCLK1 <= '0';
  sigCDSCLK2 <= '0';
  sigADCCLK <= '0';
  spin_count <= "000000";
  --                  sample_weight <= (others => '0');
  ADC_Dres(15 DOWNTO 8) <= x"3F";
  ADC_Dres(7 DOWNTO 0) <= x"00";
  control_state <= idle;
 elsif (SYSCLK'event and SYSCLK = '1') then
  case (control_state) is
   when idle =>
    accumulator <= (others => '0');
    valid <= '0';
    ped_done <= '0';
    cds_done <= '0';
    add_sub <= '1';
    cin <= '0';
    sigDl <= (others => '0');
    CDSCLK1 <= '0';
    sigCDSCLK2 <= '0';
    sigADCCLK <= '0';
    cds_done <= '0';
    sample_count <= "1100";--need to add 3 for pipeline"1000";
    XFER1_N <= '1';
    if (sh_mode = '0') then -- if DIGITAL CDS mode
     if (ppolar_s_n = '0' and integ_s_n = '0') then 
      spin_count <= "001110"; -- length of nest state spin=
      control_state <= clamp;
     else
      control_state <= idle;
     end if;
    else -- Sample and Hold mode
     --if (trig_start = '0') then
	  if (SyncInput = '1') then
      spin_count <= "000000"; -- length of next state spin
      control_state <= sample;
     else 
      control_state <= idle;
     end if;
    end if;
   when sample => 
    CDSCLK1 <= '0';
    sigCDSCLK2 <= '1'; --tc2 min 8ns
    sigADCCLK <= '0';
    if (spin_count > 0) then
     spin_count <= spin_count - 1;
     control_state <= sample;
    else
--	 spin_count <= "000000";
     control_state <= adcclock;
    end if;
   when clamp => 
   --  changed for digital cds             CDSCLK1 <= '1'; -- sample reference here
    CDSCLK1 <= '0';
    sigCDSCLK2 <= '0';
    sigADCCLK <= '0';
    if (spin_count > 0) then
     spin_count <= spin_count - 1;
     control_state <= clamp;
    else
     spin_count <= "000000"; -- length of next state spin
     control_state <= sample; -- sample 1st group
     -- control_state <= clamptosample;
    end if;
   when clamptosample =>
    CDSCLK1 <= '0';
    sigCDSCLK2 <= '0'; 
    sigADCCLK <= '0';
    if (ppolar_s_n = '1' and integ_s_n = '0') then 
     spin_count <= "000000";--"001110"; -- length of nest state spin
     control_state <= clamp;
     --                      spin_count <= "000000"; 
     --                      control_state <= sample;
    else
     control_state <= clamptosample;
    end if;
   when  adcclock =>
    CDSCLK1 <= '0';
    sigCDSCLK2 <= '0';
    sigADCCLK <= '1'; -- min pulsewidth = 30nsec
    if (spin_count > 0) then
     spin_count <= spin_count - 1;
     control_state <= adcclock;
    else 
     sample_count <= sample_count - 1;
     spin_count <= "000010";
     control_state <= latchhighdata;
    end if;
   when  latchhighdata => 
    CDSCLK1 <= '0';
    sigCDSCLK2 <= '0';
    sigADCCLK <= '1';
    sigDl(18 downto 8) <= ('0','0','0',DataIn(7),DataIn(6),DataIn(5),DataIn(4),DataIn(3),DataIn(2),DataIn(1),DataIn(0)); 
    if (spin_count > 0) then
     spin_count <= spin_count - 1;
     control_state <= latchhighdata;
    else
     spin_count <= "000010";--spin_count <= "000010";
     control_state <= hightolow;
    end if;
   when  hightolow => 
    CDSCLK1 <= '0';
    sigCDSCLK2 <= '0';
    sigADCCLK <= '0';
    if (spin_count > 0) then
     spin_count <= spin_count - 1;
     control_state <= hightolow;
    else
--!!!!!!!!!     D_latch(18 downto 0) <= accumulator(18 downto 0);
     spin_count <= "000001";-- for mult_out in next state
     control_state <= latch_low;
    end if;
   when latch_low =>          
    XFER1_N <= '0';
	 sigDl(7 downto 0) <= DataIn(7 downto 0); -- low byte
    if (spin_count > 0) then
     spin_count <= spin_count - 1;
     control_state <= latch_low;
    else 
     accumulator(18 downto 0) <= addsub_out(18 downto 0);
     -- accumulator(18 downto 0) <= accumulator(18 downto 0) + sigDl(18 downto 0);
     -- accumulator(18 downto 0) <= accumulator(18 downto 0) + mult_out(18 downto 0);
control_state <= xfer;
-------------------     control_state <= pedtosig;
    end if;
   when pedtosig =>
    --ADC_D(15 downto 0) <= accumulator(18 downto 3);
    XFER1_N <= '1'; -- turn this on to see every stage
    spin_count <= "000000";
    if (sample_count = "1011") then --pipeline n-2 sample 8 done --11
     add_sub <= '1';
     valid <= '0';
     cin <= '0';
     accumulator <= (others => '0');
     -- spin_count <= "000000";-- length of next state spin
     control_state <= sample;
    elsif (sample_count = "1010") then --pipeline n-1 sample 7 done --10
     add_sub <= '1';
     valid <= '1';
     cin <= '0';
     accumulator <= (others => '0');
     -- spin_count <= "000000";-- length of next state spin
     control_state <= sample;
    elsif (sample_count = "1001") then --pipeline n=s8 sample 6 done --9
     add_sub <= '1';--add
     cin <= '0';
     -- accumulator <= (others => '0');
     control_state <= sample;
    elsif (sample_count = "1000") then --> s7 sample 5 done --8
     ped_done <= '1';
     -- spin_count <= "001110";
     add_sub <= '1';--add
     cin <= '0';
     control_state <= clamptosample;
    elsif (sample_count = "0111") then --> s6 sample 4 done --7
     add_sub <= '1';--add
     cin <= '1';
     -- spin_count <= "000000";-- length of next state spin
     control_state <= sample;
    elsif (sample_count = "0110") then --> s5 sample 3 done --6
     add_sub <= '1';--add
     cin <= '0';
     -- spin_count <= "000000";-- length of next state spin
     control_state <= sample;
    elsif (sample_count = "0101") then --> s4 sample 2 done --5
     add_sub <= '0';
     cin <= '1';
     -- spin_count <= "000000";-- length of next state spin
     control_state <= sample;
    elsif (sample_count = "0100") then --> s3 sample 1 done --4
     add_sub <= '0';
     cin <= '1';
     -- spin_count <= "000000";-- length of next state spin
     control_state <= sample;
    elsif (sample_count = "0011") then --> s2 sample DC1 done --3
     add_sub <= '0';
     cin <= '1';
     -- spin_count <= "000000";-- length of next state spin
     control_state <= sample;
    elsif (sample_count = "0010") then --> s1 sample DC2 done --2
     add_sub <= '0';
     cin <= '1';
     -- spin_count <= "000000";-- length of next state spin
     control_state <= sample;
    elsif (sample_count = "0001") then --> dc1 sample DC3 done --1
     add_sub <= '0';
     -- accumulator <= (others => '0');
     cin <= '1';
     -- spin_count <= "000000";-- length of next state spin
     control_state <= sample;
     --XFER1_N <= '1';
     cds_done <= '1';
    elsif (sample_count = "0000") then --> dc2 sample DC4 done
     add_sub <= '1';
     -- accumulator <= (others => '0');
     cin <= '0';
     -- spin_count <= "000000";-- length of next state spin
     control_state <= xfer;
    end if;                 
   when xfer =>
    XFER1_N <= '1';
    -- ADC_D(15 downto 0) <= accumulator(15 downto 0);
    ADC_Dres(15 DOWNTO 0) <= sigDl(15 downto 0);
	 if(SyncInput = '0')then
     control_state <= idle;
	 end if;
   when others =>
    control_state <= idle;
  end case;
 end if;
end process;
Dl <= sigDl;

sample_trig : process(SYSCLK, GReset) -- one channel mode only
begin
 if (GReset = '1') then
  clock_count <= "001111111";-- was"1111000";
  trig_state <= idle_trig;
  trigger <= '1';
 elsif (SYSCLK'event and SYSCLK = '1') then
  case (trig_state) is
   when idle_trig =>
    if (clock_count > 0) then --was"000000"
     clock_count <= clock_count - 1;
     trig_state <= idle_trig;
     trigger <= '1';
    else 
     trigger <= '0';
     trig_state <= trig_out;
    end if;
   when trig_out =>
    trigger <= '0';
    clock_count <= "001111111"; -- was"1111000";
    trig_state <= idle_trig;
  end case;
 end if;
end process;

leachtest_trig : process(SYSCLK, GReset) -- one channel mode only
begin
 if (GReset = '1') then
  ltclock_count <= "111111111";
  lttrig_state <= idle_lttrig;
  ppol_n <= '1';
  integ_n <= '1';
 elsif (SYSCLK'event and SYSCLK = '1') then
  case (lttrig_state) is
   when idle_lttrig =>
    case ltclock_count is
     when "111111110" => --510
      ppol_n <= '0';
      integ_n <= '1';
     when "110011011" => --411
      ppol_n <= '0';
      integ_n <= '0';
     when "101101001" =>  -- T must >= clamp state
      ppol_n <= '1';
      integ_n <= '1';
     when "101010011" => --339
      ppol_n <= '1';
      integ_n <= '0';
     when "100100001" => --289
      ppol_n <= '1';
      integ_n <= '1';
     when "000000000"=>
      lttrig_state <= lttrig_out;
     when others =>
      lttrig_state <= idle_lttrig;
     end case;
     ltclock_count <= ltclock_count - 1;
     lttrig_state <= idle_lttrig;
   when lttrig_out =>
    ltclock_count <= "111111111";
    lttrig_state <= idle_lttrig;
  end case;
 end if;
end process;

trig_config:process(trigger,internal_trig,trig_s,ppol_n,integ_n,jp5in1sync,jp5in2sync)--SyncInput)
begin 
 if internal_trig = '1' then
  trig_start <= trigger;
  ppolar_s_n <= ppol_n;
  integ_s_n <= integ_n;
 else    
  trig_start <= trig_s;--not SyncInput; -- for asserted = high
  ppolar_s_n <= jp5in1sync;
  integ_s_n <= jp5in2sync;
 end if;
end process;

trig1_sync:process(SYSCLK,SyncInput)
begin 
 if (SYSCLK'event and SYSCLK = '1') then
  trig_s <= not SyncInput; -- for asserted = high
 end if;
end process;

pos_polar_sync:process(SYSCLK,JP5IN(1))
begin 
 if (SYSCLK'event and SYSCLK = '1') then
  jp5in1sync <= JP5IN(1); -- leach pos polarity is asserted low
 end if;
end process;

integ_sync:process(SYSCLK,JP5IN(2))
begin 
 if (SYSCLK'event and SYSCLK = '1') then
  jp5in2sync <= JP5IN(2); -- leach integ input asserted low
 end if;
end process;
--  with sample_count select
--  sample_number <=    grp1_s1 when "0111",
--                      grp1_s2 when "0110",
--                      grp1_s3 when "0101",
--                      grp1_s4 when "0100",
--                      grp2_s1 when "0011",
--                      grp2_s2 when "0010",
--                      grp2_s3 when "0001",
--                      grp2_s4 when "0000",
--                      grp1_s1 when others;
--with sample_number select
--  sample_weight <=    weight1 when grp1_s1,
--                      weight1 when grp1_s2,
--                      weight1 when grp1_s3,
--                      weight1 when grp1_s4,
--                      weight1 when grp2_s1,
--                      weight1 when grp2_s2,
--                      weight1 when grp2_s3,
--                      weight1 when grp2_s4;
 OUFLOW1 <= '0';
 SDATA <= xmt_out;
 --   JP5IN(1) <=  SyncInput;--  CDSCLK2;
 --   JP5IN(2) <=  CDSCLK2;--ADCCLK;
 JP5IN(3) <=  integ_n;--CDSCLK1;--integ_n;--CDSCLK2;
 CDSCLK2 <= sigCDSCLK2;
 JP5IN(4) <=  sigCDSCLK2;--SDATA;
 ADCCLK <= sigADCCLK;
 JP5IN(5) <=  sigADCCLK; --XFER1_N;--SCLK;   
 --   DEBUG1 <= send_config;

 -- end debug
end ArchCompAD9826control;
 --------------------------------------------------------------------------------